unit dmMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, XMLCfg, LResources, SynHighlighterCpp, SynHighlighterCss,
  SynHighlighterPas, SynHighlighterHTML, SynHighlighterJava, SynHighlighterLFM,
  SynHighlighterPerl, SynHighlighterPHP, SynHighlighterPython,
  SynHighlighterSQL, SynHighlighterTeX, synhighlighterunixshellscript,
  SynHighlighterVB, SynHighlighterXML, SynEditHighlighter,
  Contnrs, process;

type

  { TdataMain }

  TdataMain = class(TDataModule)
    HighlighterCpp: TSynCppSyn;
    HighlighterCss: TSynCssSyn;
    HighlighterFreePascal: TSynFreePascalSyn;
    HighlighterHTML: TSynHTMLSyn;
    HighlighterJava: TSynJavaSyn;
    HighlighterLFM: TSynLFMSyn;
    HighlighterPas: TSynPasSyn;
    HighlighterPerl: TSynPerlSyn;
    HighlighterPHP: TSynPHPSyn;
    HighlighterPython: TSynPythonSyn;
    HighlighterSQL: TSynSQLSyn;
    HighlighterTeX: TSynTeXSyn;
    HighlighterUNIXShellScript: TSynUNIXShellScriptSyn;
    HighlighterVB: TSynVBSyn;
    HighlighterXML: TSynXMLSyn;
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
  private
    FXMLConfig: TXMLConfig;
    FProcessList: TObjectList;
  public
    // Recent files
    procedure GetRecentFileList(const Files: TStrings);
    procedure WriteRecentFileList(const Files: TStrings);
    procedure AddToRecentFileList(const AFilename: String);
    // XML file setters and getters
    function  GetApplicationSetting(const APath, ADefault: String): String;
    function  GetApplicationSetting(const APath: String; ADefault: Integer): Integer;
    function  GetApplicationSetting(const APath: String; ADefault: Boolean): Boolean;
    procedure SetApplicationSetting(const APath, AValue: String);
    procedure SetApplicationSetting(const APath: String; AValue: Integer);
    procedure SetApplicationSetting(const APath: String; AValue: Boolean);
    // Highlighters
    function FindHighlighterByExtension(const AExtension: String): TSynCustomHighlighter;
    // Processes
    procedure KillAllProcesses;
    procedure RegisterProcess(const AProcess: TProcess);
    procedure CloseProcess(const AProcessID: Integer);
  end; 

var
  dataMain: TdataMain;

implementation

uses Math, SysUtils;

{ TdataMain }

procedure TdataMain.DataModuleCreate(Sender: TObject);
begin
  FXMLConfig := TXMLConfig.Create(nil);
  with FXMLConfig do
  begin
    RootName := 'CompuTeX';
    Filename := 'computex.xml';
  end;
  FProcessList := TObjectList.Create(True);
end;

procedure TdataMain.DataModuleDestroy(Sender: TObject);
begin
  if Assigned(FXMLConfig) then
  begin
    FXMLConfig.Flush;
    FXMLConfig.Free;
  end;
  if Assigned(FProcessList) then
  begin
    KillAllProcesses;
    FProcessList.Free;
  end;
end;

procedure TdataMain.GetRecentFileList(const Files: TStrings);
var i, max: Integer;
begin
  max := Min(
   FXMLConfig.GetValue('CompuTeX/RecentFiles/Count', 0),
   FXMLConfig.GetValue('CompuTeX/RecentFiles/Max', 10)
  );
  Files.Clear;
  for i := 0 to max - 1 do
    Files.Add(FXMLConfig.GetValue('CompuTeX/RecentFiles/File' + IntToStr(i), ''));
end;

procedure TdataMain.WriteRecentFileList(const Files: TStrings);
var i : Integer;
   max: Integer;
begin
  max := Min(
    Files.Count,
    FXMLConfig.GetValue('CompuTeX/RecentFiles/Max', 10)
  );
  for i := 0 to max - 1 do
    FXMLConfig.SetValue('CompuTeX/RecentFiles/File' +  IntToStr(i), Files[i]);
  FXMLConfig.SetValue('CompuTeX/RecentFiles/Count', Files.Count);
  FXMLConfig.Flush;
end;

procedure TdataMain.AddToRecentFileList(const AFilename: String);
var RecentFiles: TStringList;
    i: Integer;
begin
  RecentFiles := TStringList.Create;
  try
    GetRecentFileList(RecentFiles);
    i := RecentFiles.IndexOf(AFilename);
    if i > -1 then
      RecentFiles.Delete(i);
    RecentFiles.Insert(0, AFilename);
    WriteRecentFileList(RecentFiles);
  finally
    RecentFiles.Free;
  end;
end;

function TdataMain.GetApplicationSetting(const APath, ADefault: String
  ): String;
begin
  Result := FXMLConfig.GetValue(FXMLConfig.RootName + '/' + APath, ADefault);
end;

function TdataMain.GetApplicationSetting(const APath: String; ADefault: Integer
  ): Integer;
begin
  Result := FXMLConfig.GetValue(FXMLConfig.RootName + '/' + APath, ADefault);
end;

function TdataMain.GetApplicationSetting(const APath: String; ADefault: Boolean
  ): Boolean;
begin
  Result := FXMLConfig.GetValue(FXMLConfig.RootName + '/' + APath, ADefault);
end;

procedure TdataMain.SetApplicationSetting(const APath, AValue: String);
begin
  FXMLConfig.SetValue(FXMLConfig.RootName + '/' + APath, AValue);
  FXMLConfig.Flush;
end;

procedure TdataMain.SetApplicationSetting(const APath: String; AValue: Integer
  );
begin
  FXMLConfig.SetValue(FXMLConfig.RootName + '/' + APath, AValue);
  FXMLConfig.Flush;
end;

procedure TdataMain.SetApplicationSetting(const APath: String; AValue: Boolean
  );
begin
  FXMLConfig.SetValue(FXMLConfig.RootName + '/' + APath, AValue);
  FXMLConfig.Flush;
end;

function TdataMain.FindHighlighterByExtension(const AExtension: String
  ): TSynCustomHighlighter;
var i : Integer;
begin
  Result := nil;
  for i := 0 to ComponentCount - 1 do
    if Components[i] is TSynCustomHighlighter then
      if Pos(AExtension, TSynCustomHighlighter(Components[i]).DefaultFilter) > 0 then
      begin
        Result := TSynCustomHighlighter(Components[i]);
        Exit;
      end;
end;

procedure TdataMain.KillAllProcesses;
var i : Integer;
begin
  for i := FProcessList.Count - 1 downto 0 do
    CloseProcess(TProcess(FProcessList[i]).ProcessID);
end;

procedure TdataMain.RegisterProcess(const AProcess: TProcess);
begin
  FProcessList.Add(AProcess);
end;

procedure TdataMain.CloseProcess(const AProcessID: Integer);
var i : Integer;
    Index: Integer;
    Process: TProcess;
begin
  Index := -1;
  for i := 0 to FProcessList.Count - 1 do
    if TProcess(FProcessList[i]).ProcessID = AProcessID then
    begin
      Index := i;
      Break;
    end;
  if Index = -1 then Exit;
  Process := TProcess(FProcessList[Index]);
  while Process.Running do
  begin
      Process.Terminate(-1);
      Process.WaitOnExit;
  end;
  FProcessList.Remove(Process);
end;

initialization
  {$I dmMain.lrs}

end.

